

// https://www.baidu.com/link?url=CJnL3j-ykNvvbA3kyjCwZwEPneQbaSFn0YVYN6sSWhH2uZEmldfUS6OA7PJg7cWcDYNlAQSWC9odyIsBDWqkYDYq7a7s5JKcwOpaDCFKEHC&wd=&eqid=8958960a000081770000000562f3867c


import Vue from "vue";

import VueRouter from "vue-router";

Vue.use(VueRouter)

//重写路由器的push方法
// 1.先获取原始的push方法,供自定义push中使用

const lastPush = VueRouter.prototype.push
/* 
  为什么要重写push,因为push方法返回promise实例,但是如果我们不传递第三个参数onAbort,则push内部的catch函数没有处理异常的回调函数,所以如果push出错,就会直接抛出错误到浏览器上
*/
//2.重写push,覆盖之前的push方法,但是我们的push方法默认传入了onComplate和onAbort参数的默认参数为一个函数,那么如果push出现问题后,就会有catch的函数帮我们处理异常了,这个就是重写push的核心

VueRouter.prototype.push = function (
  laction,
  onComplate = () => { },
  onAbort = () => { }
) {
  /* 
  因为之前的push在VueRouter的原型对象上放,所以原本的push中this就是指向VueRouter的实例
  但是现在lastPush被直接默认调用,所以this就指向了undefined了,内部很可能出错
  我们在调用lastPush的时候,可以改变他的this指向VueRouter的实例
*/
  return lastPush.call(this, laction, onComplate, onAbort)
}

//懒加载
const Home = (() => { return import("@pages/Home") })
const Register = (() => { return import("@pages/Register") })
const Search = (() => { return import("@pages/Search") })
const Login = (() => { return import("@pages/Login") })
const Detail = (() => { return import("@pages/Detail") })
const AddCartSuccess = (() => { return import("@pages/AddCartSuccess") })
const ShopCart = (() => { return import("@pages/ShopCart") })


const Center = (() => { return import("@pages/Center") })
const Pay = (() => { return import("@pages/Pay") })
const PaySuccess = (() => { return import("@pages/PaySuccess") })
const Trade = (() => { return import("@pages/Trade") })


const MyOrder = (() => { return import("@pages/Center/MyOrder") })
const TeamOrder = (() => { return import("@pages/Center/TeamOrder") })

// 引入vueX
import store from "@/store";

const router = new VueRouter({
  //切换路由的滚动条
  scrollBehavior() {
    return {
      x: 0,
      y: 0
    }
  },
  mode: "history",
  routes: [
    {
      path: "/center", component: Center,
      children: [
        { path: "myorder", component: MyOrder, name: "myorder" },
        { path: "teamorder", component: TeamOrder, name: "teamorder" },
        // { path: "", component: MyOrder },
        {
          path: "",
          redirect: "/center/myorder",
        },
      ]
    },

    {
      path: "/pay", name: "pay", component: Pay,
      beforeEnter(to, from, next) {
        if (from.path.startsWith('/trade')) {
          next()
        } else {
          next(false)
        }
      }
    },
    {
      path: "/paysucess", name: "paysucess", component: PaySuccess,
      beforeEnter(to, from, next) {
        if (from.path.startsWith('/pay')) {
          next()
        } else {
          next(false)
        }
      }
    },
    {
      path: "/trade", name: "trade", component: Trade,
      beforeEnter(to, from, next) {
        if (from.path.startsWith('/shopcart')) {
          next()
        } else {
          next('/shopcart')
        }
      }
    },

    { path: "/home", name: "home", component: Home },
    //合并params 和 query
    {
      path: "/search/:keyword?",
      name: "search",
      component: Search,
      props(route) {
        return { ...route.query }
      }
    },
    /* 给路由身上传递meta属性  */
    {
      path: "/login",
      name: "login",
      component: Login,
      meta: { footerIsHidden: true },
      beforeEnter(to, from, next) {
        const token = store.state.user.token;
        //干嘛的 有token去主页 没有token 放行 去登录
        if (token) {
          next("/")
        } else {
          next()
        }
      }
    },
    // 商品详情路由
    { path: "/detail/:skuId", name: "detail", component: Detail },
    { path: "/shopcart", name: "shopcart", component: ShopCart },
    {
      path: "/addcartsucess", name: "addcartsucess", component: AddCartSuccess,
      /* c.只有携带的skuNum以及sessionStorage中有skuInfo数据, 才能查看添加购物车成功的界面 */
      beforeEnter(to, from, next) {
        // const skuInfo = JSON.parse(sessionStorage.getItem("cartData"));

        // if (skuInfo instanceof Object) {
        //   next();
        // }
        // //有数据可以购物车成功 没数据直接取购物车管理页面 ？
        if (sessionStorage.getItem("cartData")) {
          next();
        }
        else {
          next("/shopcart");
        }
      },
    },

    { path: "/register", name: "register", component: Register, meta: { footerIsHidden: true } },
    //默认路由
    { path: "/", redirect: "/home" }
  ],
})


/* 
  token校验逻辑:(目的:判断是否登录,并且登录后想要用户名)
    - 完成登录逻辑,拿到token,保存起来
    - 确定哪些页面需要token才能进入,哪些页面不需要token就可以进入
    - 因为每次进入路由前都要进行校验,所以我们选用全局前置守卫

    - 首先判断用户名是否存在,如果存在,则说明用户肯定是登录状态,并且我们也拥有的用户名,则直接放行

    - 在判断当前要去的路由是否是需要登录(token)的,然后再进行下一步操作
      - 如果当前的要去的路由地址不需要登录,则直接放行...
      - 如果当前的要去的路由地址需要登录,则检测是否拥有token
        - 如果拥有token,则获取一下用户名,并放行 
        - 如果没有token直接去登录页登陆以后,再来访问当前路由

*/

router.beforeEach(async (to, from, next) => {
  /* 
    to:要去的路由对象
    from:来源的路由对象
    next:决定下一步的操作
      - next():直接放行,去往to的路由地址
      - next("/login"):不再去往to的地址,而是去往next规定的地址
  */

  //使用一个数组,保存所有必须有token才能访问的路由地址
  const checkPath = ["/center", "/pay", "/paysuccess", "/trade", "/shopcart"];

  //得到当前to的地址是否在checkPath中
  const isCheckPath = checkPath.some((item) => {
    //判断to.path 是否以 item为开头(考虑多级路由的请求)
    return to.path.startsWith(item);
  });

  //获取vuex中的token和用户名
  const token = store.state.user.token;
  const nickName = store.state.user.nickName;
  //1
  if (nickName) {
    return next();
  }

  //2
  if (isCheckPath) {
    //当前路径需要token校验
    //首先判断是否拥有token
    // if (token) {
    //   //如果有token,则获取一下用户名,并放行
    //   store.dispatch("user/getUserName");
    //   next();
    // }
    //  else {
    //   //如果没有token则直接去登录页登录
    //   next("/login");
    // }

    if (token) {
      // console.log(1);
      //如果有token,则获取一下用户名,并放行
      try {
        //dispatch方法的返回值就是这个actions方法的返回值
        await store.dispatch("user/getUserName");
        next();
      } catch (e) {
        next("/login");
      }
    } else {
      //如果没有token则直接去登录页登录
      next("/login");
    }


  } else {
    //当前路由不需要token校验(但是如果此时你是有token的,我们可以顺便获取一下用户名) //如果有token,则获取一下用户名,并放行
    if (token) {
      // store.dispatch("user/getUserName");
      try {
        //dispatch方法的返回值就是这个actions方法的返回值
        await store.dispatch("user/getUserName");
        next();
      } catch (e) {
        next("/login");
      }
    }
    next();
  }
});



export default router
